package com.alibaba.citrus.cr.mn.order.center.facade.function.assemble.impl.returnorder;

import com.alibaba.citrus.cr.common.enums.ordercenter.OrderCategoryEnum;
import com.alibaba.citrus.cr.common.enums.ordercenter.SalesOrgTypeEnum;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.CustomerCenterAdapter;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.dataobject.response.CostCenterDTO;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.dataobject.response.ItemSearchAbilityDTO;
import com.alibaba.citrus.cr.mn.order.center.facade.adapter.dataobject.response.SalesBizOrgQueryDTO;
import com.alibaba.citrus.cr.mn.order.center.facade.function.assemble.OrderBizAssemble;
import com.alibaba.citrus.cr.mn.order.center.forecastorder.ability.NormalPriceQueryUtils;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.crforecastsales.model.dto.SubOrderInfo;
import com.epoch.app.crforecastsales.sdo.MainOrderInfo;
import com.epoch.app.crpricecenter.model.enums.PriceTypeEnum;
import com.epoch.app.mnordercenter.model.dto.PolicyPriceMainRequest;
import com.epoch.app.mnordercenter.model.dto.PolicyPriceQueryRequest;
import com.epoch.app.mnordercenter.model.dto.ReturnOrderBizCreateRequest;
import com.epoch.app.mnordercenter.model.dto.SalesOrderAtomCreateLineRequest;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author zhangxiaorui
 * @ClassName OrderBizAssembleOfStrategyCenter
 * @description: TODO
 * @date 2023/05/17 09:53
 * @version: 1.0
 */
@Service
@Order(5)
public class ReturnOrderBizAssembleOfCostCenter implements OrderBizAssemble<ReturnOrderBizCreateRequest> {

    private static final Log log = Log.getLogger(ReturnOrderBizAssembleOfCostCenter.class);

    @Resource
    private NormalPriceQueryUtils normalPriceQueryUtils;
    @Resource
    private CustomerCenterAdapter customerCenterAdapter;

    @Override
    public Map<String, Object> query(ReturnOrderBizCreateRequest salesOrderBizBatchCreateRequest) {
        Map<String, Object> result = Maps.newHashMap();

        result.put(String.format("costCenterCode_%s", "XA"), String.format("costCenterName_%s", "XA"));

        return result;
    }

    @Override
    public Map<String, Object> query(List<ReturnOrderBizCreateRequest> orderBizCreateRequests) {
        if (CollectionUtils.isNotEmpty(orderBizCreateRequests) && OrderCategoryEnum.GROUP.getCode().equals(orderBizCreateRequests.get(0).getOrderCategoryCode())) {
            List<String> costCenterCodeList = orderBizCreateRequests.stream()
                    .filter(a -> StringUtils.isNotBlank(a.getCostCenterCode()))
                    .map(ReturnOrderBizCreateRequest::getCostCenterCode)
                    .distinct()
                    .collect(Collectors.toList());
            List<CostCenterDTO> costCenterDTOS = customerCenterAdapter.queryCostCenter(costCenterCodeList);
            log.info("ReturnOrderBizAssembleOfCostCenter#queryCostCenter costCenterDTOS: {}", costCenterDTOS);
            if (CollectionUtils.isEmpty(costCenterDTOS)) {
                return Maps.newHashMap();
            }
            Map<String, CostCenterDTO> costCenterDTOMap = costCenterDTOS.stream().collect(Collectors.toMap(CostCenterDTO::getCostCenterCode, Function.identity(), (k1, k2) -> k2));

            Map<String, Object> result = Maps.newHashMap();
            result.put(COST_CENTER, costCenterDTOMap);
            return result;
        } else {
            return Maps.newHashMap();
        }
    }

    @Override
    public Result<String> assemble(Map<String, Object> queryResponseMap, ReturnOrderBizCreateRequest createRequest) {

        Map<String, PolicyPriceQueryRequest> subOrderPriceMap = queryGoodsDetailPrice(createRequest, queryResponseMap);

        if (OrderCategoryEnum.GROUP.getCode().equals(createRequest.getOrderCategoryCode()) && StringUtils.isNotBlank(createRequest.getCostCenterCode())) {
            Map<String, CostCenterDTO> costCenterDTOMap = getBizInfoMap(queryResponseMap, COST_CENTER, CostCenterDTO.class);
            CostCenterDTO costCenterDTO = costCenterDTOMap.get(createRequest.getCostCenterCode());
            if (Objects.isNull(costCenterDTO) || Objects.isNull(costCenterDTO.getCostCenterName())) {
                return Result.fail(createRequest.getSourceOrderNo(), "OC-01-001-01-16-029", "成本中心不存在");
            }
            createRequest.setCostCenterName(costCenterDTO.getCostCenterName());
        }

        for (SalesOrderAtomCreateLineRequest orderDetail : createRequest.getOrderDetails()) {

            String priceLineKey = orderDetail.getProductCode() + "-" + orderDetail.getSalesUnitCode();
            PolicyPriceQueryRequest subOrderInfo = subOrderPriceMap.get(priceLineKey);
            if (Objects.isNull(subOrderInfo) || Objects.isNull(subOrderInfo.getUnitPrice()) || subOrderInfo.getUnitPrice() < 0L) {
                return Result.fail(createRequest.getSourceOrderNo(), "OC-01-001-01-16-023", "价格格式错误");
            }

            Long unitPrice = subOrderInfo.getUnitPrice();
            BigDecimal unitPriceNYC = new BigDecimal(String.valueOf(unitPrice)).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);
            orderDetail.setUnitPrice(unitPriceNYC.toPlainString());

            if (StringUtils.isBlank(orderDetail.getProductQuantity())) {
                continue;
            }
            Long totalAmount = unitPrice * Long.parseLong(orderDetail.getProductQuantity());
            BigDecimal totalAmountNYC = new BigDecimal(String.valueOf(totalAmount)).divide(new BigDecimal("100"), 2, RoundingMode.HALF_UP);

            // 常规总金额
            orderDetail.setTotalAmount(totalAmountNYC.toPlainString());
            // 手工总金额/数量 = 手工单价
            if (StringUtils.isNotBlank(orderDetail.getManualTotalAmount())) {
                BigDecimal manualPrice = new BigDecimal(orderDetail.getManualTotalAmount())
                        .divide(new BigDecimal(orderDetail.getProductQuantity()), 2, RoundingMode.HALF_UP);
                orderDetail.setManualPrice(manualPrice.toPlainString());
            }
        }

        return Result.success(null);
    }

    private Map<String, PolicyPriceQueryRequest> queryGoodsDetailPrice(ReturnOrderBizCreateRequest request, Map<String, Object> queryResponseMap) {
        PolicyPriceMainRequest priceMainRequest = convertPriceMainOrder(request);

        log.info("ReturnOrderBizAssembleOfCostCenter#queryGoodsDetailPrice priceMainRequest: {} priceMainRequest: {}",
                priceMainRequest);
        List<PolicyPriceQueryRequest> policyPriceQueryRequests = normalPriceQueryUtils.queryPolicyPrice(priceMainRequest);
        log.info("ReturnOrderBizAssembleOfCostCenter#queryGoodsDetailPrice policyPriceQueryRequests: {}", policyPriceQueryRequests);
        return Optional.ofNullable(policyPriceQueryRequests).orElse(Lists.newArrayList())
                .stream().collect(Collectors.toMap(o -> o.getMaterialCode() + "-" + o.getSalesUnitCode(), p -> p, (v1, v2) -> v1));
    }

    private PolicyPriceMainRequest convertPriceMainOrder(ReturnOrderBizCreateRequest request) {
        log.info("=============convertMainOrder_request:" + JSON.toJSON(request));
        PolicyPriceMainRequest mainOrderInfo = new PolicyPriceMainRequest();
        mainOrderInfo.setFromSys(request.getFromSys());
        mainOrderInfo.setSalesOrganizationCode(request.getSalesOrganizationCode());
        mainOrderInfo.setBusinessType(request.getBusinessType());

        log.info("=============convertMainOrder_mainOrderInfo:" + JSON.toJSON(mainOrderInfo));
        mainOrderInfo.setCalculateItemList(convertPriceOrderLine(request.getOrderDetails(), request));
        return mainOrderInfo;
    }

    private List<PolicyPriceQueryRequest> convertPriceOrderLine(List<SalesOrderAtomCreateLineRequest> orderDetails, ReturnOrderBizCreateRequest request) {
        if (CollectionUtils.isEmpty(orderDetails)) {
            return Lists.newArrayList();
        }

        String priceTypeCode = PriceTypeEnum.ZP01.getCode(); // 默认查询常规价
        if (OrderCategoryEnum.GROUP.getCode().equals(request.getOrderCategoryCode())) {
            priceTypeCode = PriceTypeEnum.ZMN1.getCode(); // 集团销售订单查询到岸价
        }

        List<PolicyPriceQueryRequest> responses = Lists.newArrayList();
        for (SalesOrderAtomCreateLineRequest orderLine : orderDetails) {
            if (StringUtils.isNotBlank(orderLine.getProductCode())) {
                PolicyPriceQueryRequest response = PolicyPriceQueryRequest.builder()
                        .priceTypeCode(priceTypeCode)
                        .orgSalesOrganizationCode(request.getSalesOrganizationCode())
                        .channelCode(request.getBusinessChannel())
                        .scItemGroupCode(request.getProductGroupCode())
                        .customerCode(request.getCustomerCode())
                        .customerSaleAddressCode(request.getCustomerCode())
                        .customerSendAddressCode(request.getShipToPartyCode())
                        .salesUnitCode(orderLine.getSalesUnitCode())
                        .materialCode(orderLine.getProductCode())
                        .departmentCode(request.getSalesDepartmentCode())
                        .factoryCode(orderLine.getDeliveryFactoryCode())
                        .storePlace(orderLine.getStockCode())
                        .build();
                responses.add(response);
            }
        }
        return responses;
    }

    private MainOrderInfo convertMainOrder(ReturnOrderBizCreateRequest returnOrderBizCreateRequest, Map<String, Object> queryResponseMap) {
        // 销售组织、组织部门 等架构查询
        Map<String, SalesBizOrgQueryDTO> salesOrgByCodeMap = getBizInfoMap(queryResponseMap, SALES_ORGANIZATION, SalesBizOrgQueryDTO.class);

        MainOrderInfo mainOrderInfo = new MainOrderInfo();
        mainOrderInfo.setCustomerName(returnOrderBizCreateRequest.getCustomerName());
        mainOrderInfo.setCustomerCode(returnOrderBizCreateRequest.getCustomerCode());
        mainOrderInfo.setReceiveAddressCode(returnOrderBizCreateRequest.getShipToPartyCode());
        mainOrderInfo.setProductGroupCode(returnOrderBizCreateRequest.getProductGroupCode());
        mainOrderInfo.setChannelCode(returnOrderBizCreateRequest.getBusinessChannel());
        if (StringUtils.isNotBlank(returnOrderBizCreateRequest.getSalesDepartmentCode())) {
            mainOrderInfo.setDepartmentCode(String.valueOf(salesOrgByCodeMap.get(returnOrderBizCreateRequest.getSalesDepartmentCode()).getId()));
        }
        mainOrderInfo.setOrganizationCode(String.valueOf(salesOrgByCodeMap.get(SalesOrgTypeEnum.SALES_ORG.getCode() + "_" + returnOrderBizCreateRequest.getSalesOrganizationCode()).getId()));
        return mainOrderInfo;
    }

    private List<SubOrderInfo> convertOrderLine(List<SalesOrderAtomCreateLineRequest> orderLines, Map<String, Object> queryResponseMap) {
        if (CollectionUtils.isEmpty(orderLines)) {
            return Lists.newArrayList();
        }
        // 物料
        Map<String, ItemSearchAbilityDTO> scItemInfoMap = getBizInfoMap(queryResponseMap, SC_ITEM_INFO, ItemSearchAbilityDTO.class);

        List<SubOrderInfo> responses = Lists.newArrayList();
        for (SalesOrderAtomCreateLineRequest orderLine : orderLines) {
            SubOrderInfo response = SubOrderInfo.builder()
                    .detailRemark(orderLine.getNote())
                    .scItemId(scItemInfoMap.get(orderLine.getProductCode()).getScItemId())
                    .goodsCode(orderLine.getProductCode())
                    .scItemTitle(orderLine.getProductName())
                    .saleUnitCode(orderLine.getSalesUnitCode())
                    .saleUnit(orderLine.getSalesUnitName())
                    .unitConvert(orderLine.getUnitConversionRelationship())
                    .sourceLineNum(orderLine.getSourceLineNum())
                    .inventoryUnitCode(orderLine.getStockUnitCode())
                    .inventoryUnit(orderLine.getStockUnitName())
                    .build();
            responses.add(response);
        }
        return responses;
    }
}
